#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{

    // 建立日志页面并链接槽函数
    mLogWindow = new LogWindow(this); //新建子界面
    quiLog.setTitle("日志");
    quiLog.setAlignment(Qt::AlignCenter);
    quiLog.setMainWidget(mLogWindow);
    quiLog.setOnlyCloseBtn();

    connect(mLogWindow, SIGNAL(closeThis()), quiLog.getBtnMenuMClose(), SLOT(click()));
    connect(this, SIGNAL(logToLog(QString)), mLogWindow, SLOT(logToLog(QString)));

    // 定时器配置
    mTimer = new QTimer(this); //检测子站定时
    connect(mTimer, SIGNAL(timeout()), this, SLOT(scanTimer()));
    mPlotTimer = new QTimer(this); //波形图绘制定时
    connect(mPlotTimer, SIGNAL(timeout()), this, SLOT(timerSlot()));

    // 数据初始化
    connectTime = 0;
    plotTime = 0;
    slave4055.macID = 1;
    slave4210.macID = 2;
    slave4017.macID = 3;
    ui->setupUi(this);
    // UI控件的事件过滤应在建立UI之后
    ui->connectButton->installEventFilter(this);

    // 波形图初始化 2通道
    QFont legendFont = font();
    legendFont.setPointSize(9);

    ui->generalPlot->legend->setVisible(true);
    ui->generalPlot->legend->setFont(legendFont);
    ui->generalPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop | Qt::AlignLeft);
    ui->generalPlot->legend->setBrush(QBrush(QColor(255, 255, 255, 230)));
    ui->generalPlot->xAxis->setLabel("Second (s)");

    ui->generalPlot->addGraph();
    ui->generalPlot->graph(0)->setPen(QPen(Qt::red));
    ui->generalPlot->graph(0)->setName(tr("温度"));
    ui->generalPlot->addGraph();
    ui->generalPlot->graph(1)->setPen(QPen(Qt::blue));
    ui->generalPlot->graph(1)->setName(tr("湿度"));
}

MainWindow::~MainWindow()
{
    delete ui;
}
/*************************************************
**Function: scanTimer()
**Description: 定时器执行函数，用于监控各从站
**Others:执行间隔由start()内参数决定
*************************************************/
void MainWindow::scanTimer()
{
    // 时间更新，用于显示连接时间，表征定时器运行状况
    connectTime += masterCfg.iMasterCycle / 1000.0;
    ui->timeLable->setText(QString("%1:%2").arg((int)connectTime / 60).arg((int)connectTime % 60));

    // 4055的实时更新
    if (ui->i4055ConnectButton->isChecked())
    {
        slave4055.txBuf = BYTE(ui->i4055spinBox->value());
        if (!virtualConnection)
        {
            //正常连接
            if (Slave_IsConnected(slave4055.handle) == 1)
            {
                Slave_GetDIData(slave4055.handle, &(slave4055.rxBuf), &(slave4055.rxLen)); //读取4055数字量输入端口数据
                setDI();                                                                   //DI显示
            }
            else
            {
                // 从站断开，应关闭按钮以提示
                logToLog("i4055断开");
                ui->i4055ConnectButton->setChecked(false);
            }
        }
        else
        {
            slave4055.rxBuf = slaveVirtual.vi4055Rx;
            setDI(); //DI显示
        }
    }
    // 4017的实时更新
    if (ui->i4017ConnectButton->isChecked())
    {
        if (!virtualConnection)
        {
            //正常连接
            if (Slave_IsConnected(slave4017.handle) == 1)
            {
                slave4017.rxLen = 4;
                Slave_GetAIData(slave4017.handle, slave4017.rxBuf, &(slave4017.rxLen));
                set4017AIdata();
            }
            else
            {

                logToLog("i4017断开");
                ui->i4017ConnectButton->setChecked(false);
            }
        }
        //虚拟连接
        else
        {
            int i;
            for (i = 0; i < 4; i++)
            {
                slave4017.rxBuf[i] = slaveVirtual.vi4017Rx[i];
            };
            set4017AIdata();
        }
    }

    // 4210的实时更新
    if (ui->i4210ConnectButton->isChecked())
    {
        if (!virtualConnection)
        {
            //正常连接
            if (Slave_IsConnected(slave4210.handle) == 1)
            {
                //从站正常连接，执行动作
                //代码写这里
            }
            else
            {
                // 从站断开，应关闭按钮以提示
                logToLog("i4210断开");
                ui->i4210ConnectButton->setChecked(false);
            }
        }
        else
        {
            //虚拟连接
            //从站正常连接，执行动作
            //代码写这里
        }
    }
}

/*************************************************
**Function: timerSlot()
**Description: 绘图定时器
**Others:为了图像的连续性，此定时器每20ms刷新一次
*************************************************/
void MainWindow::timerSlot()
{
    plotTime += 0.02;
    if (ui->i4017ConnectButton->isChecked())
    {
        xAxis.append(plotTime);
        if (xAxis.size() > 500)
        {
            xAxis.remove(0);
        }

        yCh0.append(ui->i4017tmpSpinBox->value());
        if (yCh0.size() > 500)
        {
            yCh0.remove(0);
        }
        ui->generalPlot->graph(0)->setData(xAxis, yCh0);

        yCh1.append(ui->i4017humSpinBox->value());
        if (yCh1.size() > 500)
        {
            yCh1.remove(0);
        }
        ui->generalPlot->graph(1)->setData(xAxis, yCh1);

        ui->generalPlot->rescaleAxes();
        ui->generalPlot->replot();
    }
}
/*************************************************
**Function: eventFilter(QObject *watched, QEvent *event)
**Description: 事件过滤函数，用于捕获鼠标动作
**Input:监控控件、监控事件
**Others:无需主动调用该函数，但须在初始化时注册过滤器
*************************************************/
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == ui->connectButton)
    {
        if (event->type() == QEvent::Enter)
        {
            if (ui->connectButton->isChecked())
            {
                ui->connectButton->setText("断开连接");
            }
            else
            {
                ui->connectButton->setText("建立连接");
            }
        }
        else if (event->type() == QEvent::Leave)
        {
            if (ui->connectButton->isChecked())
            {
                if (virtualConnection)
                {
                    ui->connectButton->setText("虚拟连接");
                }
                else
                {
                    ui->connectButton->setText("正常连接");
                }
            }
            else
            {
                ui->connectButton->setText("未连接");
            }
        }
    }
    return QWidget::eventFilter(watched, event);
}
/*************************************************
**Function: on_connectButton_clicked(bool checked)
**Description: 连接按钮的执行函数
**Input: 按钮按下时的状态
*************************************************/
void MainWindow::on_connectButton_clicked(bool checked)
{
    if (checked)
    {
        masterCfg.iCardType = ui->iCardTypeBox->currentIndex() + 1;
        masterCfg.iCardInd = ui->iCardIndBox->value();
        masterCfg.iCANInd = ui->iCanIndBox->value();
        switch (ui->wCANBaudBox->currentIndex())
        {
        case 0:
        { //10K
            masterCfg.wCANBaud = 0x311c;
            break;
        }
        case 1:
        { //100K
            masterCfg.wCANBaud = 0x041c;
            break;
        }
        case 2:
        { //500K
            masterCfg.wCANBaud = 0x001c;
            break;
        }
        }
        int cycle = ui->iMasterCycleBox->value() / 10 * 10;
        masterCfg.iMasterCycle = cycle;
        ui->iMasterCycleBox->setValue(cycle);

        masterCfg.wMasterID = ui->wMasterIDBox->value();

        Mgr_AddRoute(masterCfg, &hRoute); //添加iCAN网络

        DWORD state = Mgr_StartSys();
        if (state != ICANOK) //判断是否启动
        {
            QString err = "错误代码：0x000000" + QString::number(state, 16);
            logToLog(err);
            int res = QUIWidget::showMessageBoxQuestion(err + QString("\r\n硬件未连接，是否进入虚拟调试模式"));
            switch (res)
            {
            case 16384:
            {
                virtualConnection = true;
                mPlotTimer->start(20);
                mTimer->start(masterCfg.iMasterCycle);
                ui->connectButton->setStyleSheet("color: rgb(255, 121, 3);background-color: rgb(255, 255, 188);");
                ui->connectButton->setText("虚拟连接");
                ui->statusbar->showMessage("系统进入虚拟操作模式", 2000);
                logToLog("系统进入虚拟操作模式");
                ui->i4017ConnectButton->setEnabled(true);
                ui->i4210ConnectButton->setEnabled(true);
                ui->i4055ConnectButton->setEnabled(true);
                break;
            }
            case 65536:
            {
                ui->connectButton->setStyleSheet(" ");
                ui->connectButton->setText("未连接");
                ui->connectButton->setChecked(false);
                logToLog("系统启动失败");
                ui->statusbar->showMessage("系统启动失败", 2000);
                break;
            }
            default:
                break;
            }
        }
        else
        {
            mTimer->start(masterCfg.iMasterCycle);
            mPlotTimer->start(20);
            ui->connectButton->setStyleSheet("background-color: rgb(85, 255, 127);");
            ui->connectButton->setText("正常连接");
            ui->i4017ConnectButton->setEnabled(true);
            ui->i4210ConnectButton->setEnabled(true);
            ui->i4055ConnectButton->setEnabled(true);
            logToLog("CAN网络已启动");
            ui->statusbar->showMessage("CAN网络已启动", 2000);
        }
    }
    else
    {
        on_i4017ConnectButton_clicked(false);
        on_i4210ConnectButton_clicked(false);
        on_i4055ConnectButton_clicked(false);
        if (virtualConnection)
        {
            virtualConnection = false;
        }
        else
        {
            Mgr_DelAllRoute();
            Mgr_StopSys();
        }
        mTimer->stop();
        mPlotTimer->stop();
        plotTime = 0;
        connectTime = 0;
        xAxis.clear();
        yCh0.clear();
        yCh1.clear();
        ui->timeLable->setText("↑点击按钮进行连接↑");
        ui->connectButton->setStyleSheet(" ");
        ui->connectButton->setText("未连接");
        ui->i4017ConnectButton->setEnabled(false);
        ui->i4210ConnectButton->setEnabled(false);
        ui->i4055ConnectButton->setEnabled(false);
        logToLog("断开连接");
        ui->statusbar->showMessage("断开连接", 2000);
    }
}
/*************************************************
**Function: on_actionDiplayLog_triggered()
**Description: 显示日志动作
*************************************************/
void MainWindow::on_actionDisplayLog_triggered()
{
    quiLog.exec();
}

void MainWindow::on_i4055Buttonqueding_clicked()
{
    if (!ui->i4055ConnectButton->isChecked())
    {
        QString s = "4055未连接";
        logToLog(s);
        QUIWidget::showMessageBoxError(s);
        ui->statusbar->showMessage(s, 2000);
    }
    else
    {
        if (!virtualConnection)
        {

            slave4055.txBuf = BYTE(ui->i4055spinBox->value());
            Slave_SendData(slave4055.handle, 0x20, &(slave4055.txBuf), 1); //发送数据
        }
        else
        {

            slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());


        }
    }
    setDO();
}

/*************************************************
**Function: setDI()
**Description: 正常连接时正常连接时4055输入显示DI灯
**Input:UI的指针
**Others:类外函数想直接调用UI的控件，要将UI的指针做外参数传入类外函数
*************************************************/
void MainWindow::setDI()
{
    ui->i4055ButtonDI1->setChecked(slave4055.rxBuf & 1);
    ui->i4055ButtonDI2->setChecked(slave4055.rxBuf & 2);
    ui->i4055ButtonDI3->setChecked(slave4055.rxBuf & 4);
    ui->i4055ButtonDI4->setChecked(slave4055.rxBuf & 8);
    ui->i4055ButtonDI5->setChecked(slave4055.rxBuf & 0x10);
    ui->i4055ButtonDI6->setChecked(slave4055.rxBuf & 0x20);
    ui->i4055ButtonDI7->setChecked(slave4055.rxBuf & 0x40);
    ui->i4055ButtonDI8->setChecked(slave4055.rxBuf & 0x80);
}
void MainWindow::setDO()
{
    //setDO
    ui->i4055ButtonDO1->setChecked(ui->i4055spinBox->value() & 1);
    ui->i4055ButtonDO2->setChecked(ui->i4055spinBox->value() & 2);
    ui->i4055ButtonDO3->setChecked(ui->i4055spinBox->value() & 4);
    ui->i4055ButtonDO4->setChecked(ui->i4055spinBox->value() & 8);
    ui->i4055ButtonDO5->setChecked(ui->i4055spinBox->value() & 0x10);
    ui->i4055ButtonDO6->setChecked(ui->i4055spinBox->value() & 0x20);
    ui->i4055ButtonDO7->setChecked(ui->i4055spinBox->value() & 0x40);
    ui->i4055ButtonDO8->setChecked(ui->i4055spinBox->value() & 0x80);
}

void MainWindow::sendDO()
{
    if (!ui->i4055ConnectButton->isChecked())
    {
        QString s = "4055未连接";
        logToLog(s);
        QUIWidget::showMessageBoxError(s);
        ui->statusbar->showMessage(s, 2000);
    }
    else
    {
        if (!virtualConnection)
        {

            slave4055.txBuf = BYTE(ui->i4055spinBox->value());
            Slave_SendData(slave4055.handle, 0x20, &(slave4055.txBuf), 1); //发送数据
        }

    }
    setDO();
}
/*************************************************
**Function: set4017AIdata()       // 函数名称
**Description: 将输入4017模块的电压值转化为温度和湿度值进行显示   // 函数功能描述
**Input:    虚拟连接4210的电压或正常连接输入的电压    // 输入参数说明，包括每个参数的作用、取值说明
**Others:   无      // 其它说明
*************************************************/
void MainWindow::set4017AIdata()
{

    double tmp, hum;
    double v0, v1;
    v0 = ((double)(slave4017.rxBuf[0] * 16 * 16 + slave4017.rxBuf[1]) - 0x8000) * 10 / (double)0x8000;
    v1 = ((double)(slave4017.rxBuf[2] * 16 * 16 + slave4017.rxBuf[3]) - 0x8000) * 10 / (double)0x8000;
    tmp = v0 * 6.25 - 12.5;
    hum = v1 * 12.5 - 25;
    ui->i4017tmpSpinBox->setValue(tmp);
    ui->i4017humSpinBox->setValue(hum);
    if (ui->i4017comboBox_3->currentIndex() == 0)
    {
        ui->i4017dSpinBox->setValue(v0);
        ui->i4017dSpinBox->setSuffix("V");
    }
    else
    {
        ui->i4017dSpinBox->setValue(v0 * 2);
        ui->i4017dSpinBox->setSuffix("mA");
    }
    if (ui->i4017comboBox_4->currentIndex() == 0)
    {
        ui->i4017dSpinBox_1->setValue(v1);
        ui->i4017dSpinBox_1->setSuffix("V");
    }
    else
    {
        ui->i4017dSpinBox_1->setValue(v1 * 2);
        ui->i4017dSpinBox_1->setSuffix("mA");
    }
}
/*************************************************
**Function: on_i4055ButtonDO1_clicked()
**Description: 以下函数DO和spinbox联系起来
**Input:null
**Others:8个槽函数
*************************************************/

void MainWindow::on_i4055ButtonDO1_clicked()
{
    if ((slaveVirtual.vi4055Rx & 1) != ui->i4055ButtonDO1->isChecked())
    {
        if (ui->i4055ButtonDO1->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 1);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 1);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO2_clicked()
{
    if (((slaveVirtual.vi4055Rx / 2) & 1) != ui->i4055ButtonDO2->isChecked())
    {
        if (ui->i4055ButtonDO2->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 2);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 2);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO3_clicked()
{
    if (((slaveVirtual.vi4055Rx / 4) & 1) != ui->i4055ButtonDO3->isChecked())
    {
        if (ui->i4055ButtonDO3->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 4);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 4);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO4_clicked()
{
    if (((slaveVirtual.vi4055Rx / 8) & 1) != ui->i4055ButtonDO4->isChecked())
    {
        if (ui->i4055ButtonDO4->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 8);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 8);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO5_clicked()
{
    if (((slaveVirtual.vi4055Rx / 16) & 1) != ui->i4055ButtonDO5->isChecked())
    {
        if (ui->i4055ButtonDO5->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 16);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 16);
    }
   sendDO();
   slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO6_clicked()
{
    if (((slaveVirtual.vi4055Rx / 32) & 1) != ui->i4055ButtonDO6->isChecked())
    {
        if (ui->i4055ButtonDO6->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 32);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 32);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO7_clicked()
{
    if (((slaveVirtual.vi4055Rx / 64) & 1) != ui->i4055ButtonDO7->isChecked())
    {
        if (ui->i4055ButtonDO7->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 64);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 64);
    }
    sendDO();
    slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}

void MainWindow::on_i4055ButtonDO8_clicked()
{
    if (((slaveVirtual.vi4055Rx / 128) & 1) != ui->i4055ButtonDO8->isChecked())
    {
        if (ui->i4055ButtonDO8->isChecked() == true)
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx + 128);
        else
            ui->i4055spinBox->setValue(slaveVirtual.vi4055Rx - 128);
    }
   sendDO();
   slaveVirtual.vi4055Rx = BYTE(ui->i4055spinBox->value());
}
/*************************************************
**Function: on_i4055ConnectButton_clicked(bool checked)
**Description: 连接到4055从站执行函数
**Input:按键状态：按下 or 抬起
**Others:
*************************************************/
void MainWindow::on_i4055ConnectButton_clicked(bool checked)
{
    if (checked)
    {
        if (!virtualConnection)
        {
            Route_AddSlave(hRoute, 1, &(slave4055.handle));
            if (Slave_Connect(slave4055.handle) != ICANOK)
            {
                QString s = "4055连接失败";
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
                ui->i4055ConnectButton->setChecked(false);
            }
            else
            {
                QString s = "4055连接成功";
                ui->i4055ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
            }
        }
        else
        {
            QString s = "虚拟连接到4055";
            ui->i4055ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
            ui->i4055spinBox->setValue(0); //初始DO
            setDO();
            slaveVirtual.vi4055Rx=0;       //初始DI
        }
    }
    else
    {
        if (!virtualConnection)
        {

            Slave_Disconnect(slave4055.handle);
            ui->i4055ConnectButton->setStyleSheet(" ");
            QString s = "4055已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        else
        {
            ui->i4055ConnectButton->setStyleSheet(" ");
            QString s = "虚拟4055已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        ui->i4055ConnectButton->setChecked(checked);
    }
}

/*************************************************
**Function: on_i4017ConnectButton_clicked(bool checked)
**Description: 连接到4017从站执行函数
**Input:按键状态：按下 or 抬起
**Others:
*************************************************/
void MainWindow::on_i4017ConnectButton_clicked(bool checked)
{
    if (checked)
    {
        if (!virtualConnection)
        {
            Route_AddSlave(hRoute, 2, &(slave4017.handle));
            if (Slave_Connect(slave4017.handle) != ICANOK)
            {
                QString s = "4017连接失败";
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
                ui->i4017ConnectButton->setChecked(false);
            }
            else
            {
                QString s = "4017连接成功";
                ui->i4017ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
            }
        }
        else
        {
            ui->i4017ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
            QString s = "虚拟连接到4017";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
    }
    else
    {
        if (!virtualConnection)
        {
            Slave_Disconnect(slave4017.handle);
            ui->i4017ConnectButton->setStyleSheet(" ");
            QString s = "4017已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        else
        {
            ui->i4017ConnectButton->setStyleSheet(" ");
            QString s = "虚拟4017已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        xAxis.clear();
        yCh0.clear();
        yCh1.clear();
        ui->i4017ConnectButton->setChecked(checked);
    }
}

/*************************************************
**Function: on_i4210ConnectButton_clicked(bool checked)
**Description: 连接到4210从站执行函数
**Input:按键状态：按下 or 抬起
**Others:
*************************************************/
void MainWindow::on_i4210ConnectButton_clicked(bool checked)
{
    if (checked)
    {
        if (!virtualConnection)
        {
            Route_AddSlave(hRoute, 3, &(slave4210.handle));
            if (Slave_Connect(slave4210.handle) != ICANOK)
            {
                QString s = "4210连接失败";
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
                ui->i4210ConnectButton->setChecked(false);
            }
            else
            {
                ui->i4210ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
                QString s = "4210连接成功";
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
            }
        }
        else
        {
            ui->i4210ConnectButton->setStyleSheet("background-color: rgb(170, 255, 127);");
            QString s = "虚拟连接到4210";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
    }
    else
    {
        if (!virtualConnection)
        {
            Slave_Disconnect(slave4210.handle);
            ui->i4210ConnectButton->setStyleSheet(" ");
            QString s = "4210已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        else
        {
            ui->i4210ConnectButton->setStyleSheet(" ");
            QString s = "虚拟4210已断开";
            logToLog(s);
            ui->statusbar->showMessage(s, 2000);
        }
        ui->i4210ConnectButton->setChecked(checked);
    }
}
/*************************************************
**Function: i4210电压输入控件
**Description: 调整输入4210电压
**Input:  按键状态：拖动滑块或键盘输入
**Others:
*************************************************/
void MainWindow::on_i4210dSpinBox_valueChanged(double arg1)
{
    ui->i4210Slider->setValue(arg1 * 100);
}
void MainWindow::on_i4210Slider_valueChanged(int value)
{
    ui->i4210dSpinBox->setValue((double)(value) / 100);
}

void MainWindow::on_i4210dSpinBox_1_valueChanged(double arg1)
{
    ui->i4210Slider_1->setValue((int)(arg1 * 100));
}

void MainWindow::on_i4210Slider_1_valueChanged(int value)
{
    ui->i4210dSpinBox_1->setValue((double)(value) / 100);
}
/*************************************************
**Function: on_i4210ButtonReset_clicked()
**Description: 复位从站4210电压
**Input: 按键状态：点击
**Others:
*************************************************/
void MainWindow::on_i4210ButtonReset_clicked()
{
    ui->i4210Slider->setValue(0);
    ui->i4210Slider_1->setValue(0);
    ui->i4210dSpinBox->setValue(0.00);
    ui->i4210dSpinBox_1->setValue(0.00);
    ui->statusbar->showMessage("已复位", 2000);
}
/*************************************************
**Function: on_i4210ButtonSureout_clicked()
**Description: 将4210电压转化成数字量输出到对应的数组中
**Input: 按键状态：点击
**Others:
*************************************************/
void MainWindow::on_i4210ButtonSureout_clicked()
{
    if (ui->connectButton->isChecked())
    {
        if (ui->i4210ConnectButton->isChecked())
        {
            if (!virtualConnection)
            {
                unsigned char buf[32] = {0};
                buf[1] = (unsigned short)(ui->i4210dSpinBox->value() / 10) * 65535;
                buf[0] = (unsigned short)((ui->i4210dSpinBox->value() / 10) * 65535) >> 8;
                buf[3] = (unsigned short)(ui->i4210dSpinBox_1->value() / 10) * 65535;
                buf[2] = (unsigned short)((ui->i4210dSpinBox_1->value() / 10) * 65535) >> 8;
                Slave_SendData(slave4210.handle, 0x60, buf, 4);
                QString s = "数据已发送";
                logToLog(s);
                ui->statusbar->showMessage(s, 2000);
            }
            else
            {
                slaveVirtual.vi4017Rx[1] = (unsigned short)(ui->i4210dSpinBox->value() / 10) * 65535;
                slaveVirtual.vi4017Rx[0] = (unsigned short)((ui->i4210dSpinBox->value() / 10) * 65535) >> 8;
                slaveVirtual.vi4017Rx[3] = (unsigned short)(ui->i4210dSpinBox_1->value() / 10) * 65535;
                slaveVirtual.vi4017Rx[2] = (unsigned short)((ui->i4210dSpinBox_1->value() / 10) * 65535) >> 8;
                convertRangeIn4017(); //转换量程
                QString s1 = "数据已虚拟发送";
                logToLog(s1);
                ui->statusbar->showMessage(s1, 2000);
                ui->tabWidget->setCurrentWidget(ui->tab_4017);
            }
        }
        else
        {
            QString s2 = "4210未连接，请先连接4210";
            logToLog(s2);
            QUIWidget::showMessageBoxError(s2);
        }
    }
    else
    {
        QString err = "主站未连接，请连接主站";
        logToLog(err);
        QUIWidget::showMessageBoxError(err);
    }
}
/*************************************************
**Function: on_i4017resetbutton_clicked()
**Description: 计时器停止之后，4017温湿度显示和电压显示清零
**Input: 按键状态：点击
**Others:
*************************************************/
void MainWindow::on_i4017resetbutton_clicked()
{
    ui->i4017dSpinBox->setValue(0.00);
    ui->i4017dSpinBox_1->setValue(0.00);
    ui->i4017tmpSpinBox->setValue(0);
    ui->i4017humSpinBox->setValue(0);
    ui->i4210Slider->setValue(0);
    ui->i4210Slider_1->setValue(0);
    ui->i4210dSpinBox->setValue(0.00);
    ui->i4210dSpinBox_1->setValue(0.00);
    xAxis.clear();
    yCh0.clear();
    yCh1.clear();
    ui->generalPlot->graph(0)->setData(xAxis, yCh0);
    ui->generalPlot->graph(1)->setData(xAxis, yCh1);
    ui->generalPlot->replot();
}
/*************************************************
**Function: on_actionAboutCANTest_triggered()
**Description: 关于CANTest，显示软件信息
*************************************************/
void MainWindow::on_actionAboutCANTest_triggered()
{
    QString s = QString("<b>CANTest %1</b><br>"
                        "用于CAN总线相关实验<br>"
                        "作者：ZohyCao、shawnvanbohr、LKMK、lmz<br>"
                        "开源地址：<a href=\"https://gitee.com/dxes/CANTest/\">https://gitee.com/dxes/CANTest/</a>")
                    .arg(QString::number(VT_VERSION, 'f', 2));
    QUIWidget::showMessageBoxInfo(s, "关于CANTest");
    //    HelpDialog::showHelp(this,"关于CANTest",s);
}

/*************************************************
**Function: void MainWindow::convertRangeIn4017(void)
**Description: 4017模块的量程转换
**Others: 虚拟验证时，因为只有一个虚拟变量slaveVirtual.vi4017Rx，
**        但4210输出的16位表示了0-10V
**        主站向4017读出的16位表示了±10V
** 若是直接用一个变量做中转，会存在量程不一致的问题
** 该函数模拟了4017内部的过程，
** 即读出4210发来的电压值，再转换一次发给主站
** 仅虚拟验证时使用，转换两通道的数据
*************************************************/
void MainWindow::convertRangeIn4017(void)
{
    double rCh1;
    double rCh2;
    // 读出真实值
    rCh1 = (double)(slaveVirtual.vi4017Rx[0] * 16 * 16 + slaveVirtual.vi4017Rx[1]) * 10 / (double)0xffff;
    rCh2 = (double)(slaveVirtual.vi4017Rx[2] * 16 * 16 + slaveVirtual.vi4017Rx[3]) * 10 / (double)0xffff;
    // 再转换为16位
    slaveVirtual.vi4017Rx[1] = (unsigned short)((rCh1 / 10.0) * 0x8000 + 0x7fff);
    slaveVirtual.vi4017Rx[0] = (unsigned short)((rCh1 / 10.0) * 0x8000 + 0x7fff) >> 8;
    slaveVirtual.vi4017Rx[3] = (unsigned short)((rCh2 / 10.0) * 0x8000 + 0x7fff);
    slaveVirtual.vi4017Rx[2] = (unsigned short)((rCh2 / 10.0) * 0x8000 + 0x7fff) >> 8;
}
